﻿using UnityEngine;
using System;
//List依赖
using System.Collections.Generic;
//Random依赖
using Random = UnityEngine.Random;

// 场景 棋盘管理者
public class BoardManager : MonoBehaviour {
	//设定计数用类
	[Serializable]
	public class Count {
		public int minimum;
		public int maximum;

		public Count (int min, int max) {
			minimum = min;
			maximum = max;
		}
	}
	
	//制作8*8的游戏棋盘
    //纵8格
	public int columns = 8;
    //横8格
	public int rows = 8;
	//墙壁5〜9之间随机刷新
	public Count wallCount = new Count (5,9);
	//道具1〜5之間随机刷新
	public Count foodCount = new Count (1,5);
	//Exit对象
	public GameObject exit;
	//配置复数地板・内壁・道具・敌人角色・外墙壁的数组
	public GameObject[] floorTiles;
	public GameObject[] wallTiles;
	public GameObject[] foodTiles;
	public GameObject[] enemyTiles;
	public GameObject[] outerWallTiles;

	//保存对象的位置信息的变量(生成物体相对的基准坐标)
	private Transform boardHolder;
	//用来记录对象可以配置范围的列表
	//使用List是因为可变其长度
	private List <Vector3> gridPositions = new List<Vector3>();

	//决定可以配置敌人角色・道具・内壁的范围
	void InitialiseList ()
	{
		//清空gridPosition
		gridPositions.Clear ();
		//gridPosition填充可能配置的范围
        // 为了防止玩家生成的那一行就卡住不能移动 把最外面一圈给忽略掉 
		//x = 1〜6循环 
		for (int x = 1; x < columns - 1; x++) {
			//y = 1〜6循环
			for (int y = 1; y < rows - 1; y++) {
				//6*6的范围中填充gridPositions
				gridPositions.Add(new Vector3(x, y, 0f));
			}
		}
	}
	// 配置外壁、地板
	void BoardSetup ()
	{
		//生成名为Board的对象、transform信息保存到boardHolder
		boardHolder = new GameObject ("Board").transform;
		//x = -1〜8循环
		for (int x = -1; x < columns + 1; x++) {
			//y = -1〜8循环
			for (int y = -1; y < rows + 1; y++) {
				//随机选择地板 从floorTiles的长度中随机选择一个元素
				GameObject toInstantiate = floorTiles [Random.Range (0, floorTiles.Length)];
				//左端or右端or最低部or最上部＝生成外壁的时机
				if (x == -1 || x == columns || y == -1 || y == rows) {
					//与floorTile相同随机选择外壁，因为不需要地板了，所以覆盖掉地板
					toInstantiate = outerWallTiles [Random.Range (0, outerWallTiles.Length)];
				}
				//生成地板or外壁、保存到instance变量
				GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f),
					Quaternion.identity) as GameObject;
				//生成的instance作为Board对象的子对象
				instance.transform.SetParent(boardHolder);
			}
		}
	}
	
    // 场景中的随机坐标
	Vector3 RandomPosition () {
		//0〜36(gridPositions的长度)中随机选择决定一个位置
        //
		int randomIndex = Random.Range(0, gridPositions.Count);
		Vector3 randomPosition = gridPositions[randomIndex];
		//把选择过的位置删除（这个坐标已经被使用过了 不能再放置其他对象了）
        //RemoveAt删除改List对应索引的元素
        //目的是：使得下一次被递归调用的时候使用的坐标不重复
        //假如数组是这样的
        //List<int> temp = [0,1,2,3,4,5,6,7];
        //执行temp.RemoveAt(1);
        //结果的temp就变成 temp = [0,2,3,4,5,6,7]
		gridPositions.RemoveAt(randomIndex);
		//返回决定的位置 用于生成我们的随机道具对象
		return randomPosition;
	}
	
    /// <summary>
    /// 随机生成对象
    /// </summary>
    /// <param name="tileArray">用于生成我们的Prefab游戏对象的数组</param>
    /// <param name="minimum">最少放置几个</param>
    /// <param name="maximum">最多放置几个</param>
	void LayoutObjectAtRandom (GameObject[] tileArray, int minimum, int maximum)
	{
		//进行最小値〜最大値+1的随机回数循环
        //决定这个Prefab对象会生成多少次
		int objectCount = Random.Range (minimum, maximum + 1);
		for (int i = 0; i < objectCount; i++) {
			//从gridPosition获取一个位置
			Vector3 randomPosition = RandomPosition();
			//从参数tileArray中随机选择一个游戏对象
			GameObject tileChoise = tileArray[Random.Range(0, tileArray.Length)];
			//从随机选择的种类・位置中生成
			Instantiate (tileChoise, randomPosition, Quaternion.identity);
		}
	}
	//配置对象方法
	//这个类中唯一的public方法 关系到地板生成时机所以从GameManager中调用
	public void SetupScene (int level)
	{
		//地板和墙壁
		BoardSetup();
		//决定能够 放置 敌人角色・内壁・道具配置的 位置
		InitialiseList();
		//内壁・道具・敌方角色 随机进行配置
        //通过序列化Count对象可以在Inspector调整minimum和maximum的值
        //方便我们在编辑器中修改，调整游戏难度
        //当前wallCount.minimum默认是5，wallCount.maximum默认是9
        //也就是说随机生成5-9道墙
		LayoutObjectAtRandom(wallTiles, wallCount.minimum, wallCount.maximum);
		LayoutObjectAtRandom(foodTiles, foodCount.minimum, foodCount.maximum);
		//Mathf.Log : 计算以2为底的对数。level=4是2、level=8是3
		int enemyCount = (int)Mathf.Log(level, 2f);
		LayoutObjectAtRandom(enemyTiles, enemyCount, enemyCount);
		//将Exit配置到7, 7的位置。
		Instantiate(exit, new Vector3(columns - 1, rows - 1, 0F), Quaternion.identity);
	}
}